mod mylb;
mod my_gateway;
mod app_proxy;
mod service_proxy;

use async_trait::async_trait;
use pingora::prelude::*;
use std::sync::Arc;
use pingora::services;
use pingora::services::Service;
use prometheus::register_int_counter;
use crate::my_gateway::MyGateway;
use crate::mylb::LB;
use crate::service_proxy::{proxy_service, proxy_service_tls};

fn main() {
    simple_proxy();
}

fn simple_proxy() {
    let mut my_server = Server::new(None).unwrap();
    my_server.bootstrap();

    let proxy_service = proxy_service(
        "0.0.0.0:20599", // listen
        "1.1.1.1:80",   // proxy to
    );

    let cert_path = "src/server.crt";
    let key_path = "src/key.pem";

    let proxy_service_ssl = proxy_service_tls(
        "0.0.0.0:12345",    // listen
        "1.1.1.1:443",     // proxy to
        "one.one.one.one", // SNI
        cert_path,
        key_path,
    );

    let services: Vec<Box<dyn Service>> = vec![
        Box::new(proxy_service),
        Box::new(proxy_service_ssl),
    ];
    my_server.add_services(services);
    my_server.run_forever();
}

fn my_gateway() {
    let mut my_server = Server::new(None).unwrap();
    my_server.bootstrap();

    let mut my_proxy = http_proxy_service(
        &my_server.configuration,
        MyGateway {
            req_metric: register_int_counter!("reg_counter", "Number of requests").unwrap(),
        },
    );
    my_proxy.add_tcp("0.0.0.0:20599");
    my_server.add_service(my_proxy);

    let mut prometheus_service_http =
        services::listening::Service::prometheus_http_service();
    prometheus_service_http.add_tcp("127.0.0.1:12345");
    my_server.add_service(prometheus_service_http);

    my_server.run_forever();
}

// 负载均衡
fn lb() {
    let mut my_server = Server::new(None).unwrap();
    my_server.bootstrap();

    // Note that upstreams needs to be declared as `mut` now
    let mut upstreams =
        LoadBalancer::try_from_iter(["1.1.1.1:443", "1.0.0.1:443", "127.0.0.1:343"]).unwrap();

    let hc = TcpHealthCheck::new();
    upstreams.set_health_check(hc);
    upstreams.health_check_frequency = Some(std::time::Duration::from_secs(1));

    let background = background_service("health check", upstreams);
    let upstreams = background.task();

    // `upstreams` no longer need to be wrapped in an arc
    let mut lb = http_proxy_service(&my_server.configuration, LB(upstreams));
    lb.add_tcp("0.0.0.0:20599");

    my_server.add_service(background);

    my_server.add_service(lb);
    my_server.run_forever();
}